/******************************************************************************
 * @file     bsp_led_handler.c
 * @brief    led handler层
 * @author   Ruilist
 * @date     2025-08-26
 * @version  V1.0.0
 * @copyright Copyright (c) 2025
 *
 * @note     1 tab = 4 space
 *           依赖 bsp_led_handler.h
 *
 * @par 日志:
 * - V1.0.0 2025-08-26 Ruilist
 *****************************************************************************/

//******************************** Includes *********************************//

#include "bsp_led_handler.h"

//******************************** Includes *********************************//

//******************************** Defines **********************************//

/**
 * @brief LED控制参数结构体
 */
typedef struct
{
    uint32_t         cycle;        // 闪烁周期(ms
    uint32_t         blink_times;  // 闪烁次数
    led_duty_cycle_t duty_cycle;   // 闪烁占空比
    led_index_t      index;        // LED实例索引
} led_handler_event_t;

//******************************** Defines **********************************//

//******************************** Declaring ********************************//

/**
 * @brief   LED闪烁操作函数
 *
 * @param   bsp_led_driver_t * self led实例结构体指针
 *
 * @return  led_handler_status_t 函数运行状态
 *
 * @retval  HANDLER_OK                操作成功
 * @retval  HANDLER_ERROR_PARAMETER   传入参数错误
 */
led_handler_status_t led_blink_handler( bsp_led_driver_t *self )
{
    if ( NULL == self || HANDLER_NOT_INITED == self->init_status )
    {
#ifdef DEBUG
        DEBUG_OUT( "HANDLER_ERRORPARAMETER in led_blink_handler\r\n" );
#endif  // DEBUG
        return HANDLER_ERROR_PARAMETER;
    }

    uint32_t         cycle_local;
    uint32_t         blink_times_local;
    led_duty_cycle_t duty_cycle_local;
    uint32_t         led_toggle_time;

    cycle_local       = self->cycle;
    blink_times_local = self->blink_times;
    duty_cycle_local  = self->duty_cycle;

    if ( DUTY_CYCLE_1_1 == duty_cycle_local ||
         DUTY_CYCLE_1_2 == duty_cycle_local ||
         DUTY_CYCLE_1_3 == duty_cycle_local )
    {
        led_toggle_time = cycle_local / ( duty_cycle_local + 1 );
    }
    else
    {
#ifdef DEBUG
        DEBUG_OUT( "led_blink_handler input duty_cycle_local is error\r\n" );
#endif  // DEBUG
        return HANDLER_ERROR_PARAMETER;
    }

    for ( uint32_t i = 0; i < blink_times_local; i++ )
    {
        for ( uint32_t j = 0; j < cycle_local; j++ )
        {
#ifdef OS_SUPPORTING
            self->p_os_delay->pf_os_delay( 1 );
#endif  // OS_SUPPORTING
            if ( j < led_toggle_time )
            {
                self->p_led_ops->pf_led_on();
            }
            else
            {
                self->p_led_ops->pf_led_off();
            }
        }
    }
    return HANDLER_OK;
}

/**
 * @brief   LED线程队列事件处理函数
 *
 * @param   bsp_led_driver_t * self       led实例结构体指针
 * @param   led_handler_event_t queue_rec LED事件结构体
 *
 * @return  led_handler_status_t 函数运行状态
 *
 * @retval  HANDLER_OK                操作成功
 * @retval  HANDLER_ERROR_PARAMETER   传入参数错误
 */
led_handler_status_t __event_process(
    bsp_led_handler_t  *self,
    led_handler_event_t queue_rec )
{
    if ( NULL == self )
    {
#ifdef DEBUG
        DEBUG_OUT( "__event_process input parameter is error \r\n" );
#endif  // DEBUG
        return HANDLER_ERROR_PARAMETER;
    }

    if ( ( MAX_INSTANCE_NUMBER < queue_rec.index ) ||
         ( LED_NOT_INITIALIZED == queue_rec.index ) ||
         ( NULL == self->instances.led_instance_group[queue_rec.index] ) )
    {
#ifdef DEBUG
        DEBUG_OUT( " __event_process index HANDLER_ERROR_PARAMETER\r\n" );
#endif  // DEBUG
        return HANDLER_ERROR_PARAMETER;
    }

    ( self->instances.led_instance_group[queue_rec.index] )->cycle =
        queue_rec.cycle;
    ( self->instances.led_instance_group[queue_rec.index] )->blink_times =
        queue_rec.blink_times;
    ( self->instances.led_instance_group[queue_rec.index] )->duty_cycle =
        queue_rec.duty_cycle;

    led_handler_status_t ret = HANDLER_OK;

    ret = led_blink_handler( self->instances.led_instance_group
                                 [queue_rec.index] );

    if ( HANDLER_OK != ret )
    {
#ifdef DEBUG
        DEBUG_OUT( "led_blink_handler failed at __event_process\r\n" );
#endif  // DEBUG
        return HANDLER_ERROR;
    }
    return HANDLER_OK;
}

/**
 * @brief   对LED句柄挂载LED实例索引数组初始化
 *
 * @param   bsp_led_driver_t *array[] 索引数组指针
 * @param   uint32_t array_size       初始化大小
 *
 * @return  led_handler_status_t 函数运行状态
 *
 * @retval  HANDLER_OK                操作成功
 * @retval  HANDLER_ERROR_PARAMETER   传入参数错误
 */
static led_handler_status_t __array_init( bsp_led_driver_t *array[],
                                          uint32_t          array_size )
{
    if ( ( NULL == array ) || ( 0 == array_size ) )
    {
#ifdef DEBUG
        DEBUG_OUT( "__array_init input parameter is error \r\n" );
#endif  // DEBUG
        return HANDLER_ERROR_PARAMETER;
    }
    for ( int i = 0; i < array_size; i++ )
    {
        array[i] = (bsp_led_driver_t *)NULL;
    }

    return HANDLER_OK;
}

/**
 * @brief   LED句柄线程任务
 *
 * @param   void *argument      默认参数
 *
 * @return  led_handler_status_t 函数运行状态
 *
 * @retval  NULL
 */
led_handler_status_t handler_thread( void *argument )
{
    led_handler_status_t ret = HANDLER_OK;

    bsp_led_handler_t *p_led_handler;

    led_handler_event_t queue_rec;

    if ( NULL != argument )
    {
        p_led_handler = argument;
    }

    for ( ;; )
    {
        ret = p_led_handler->p_os_queue->pf_os_queue_get(
            p_led_handler->queue_handler,
            &queue_rec,
            0 );
        if ( HANDLER_OK == ret )
        {
#ifdef DEBUG
            DEBUG_OUT( "the message received \r\n" );
#endif  // DEBUG
            __event_process( p_led_handler, queue_rec );
#ifdef DEBUG
            DEBUG_OUT( "led_blink_handler over\r\n" );
#endif  // DEBUG
        }
        p_led_handler->p_os_time_delay->pf_os_delay( 1000 );
    }
}

/**
 * @brief   LED句柄注册LED实例函数
 *
 * @param   bsp_led_handler_t *const self      led句柄结构体指针
 * @param   bsp_led_driver_t *const led_driver led实例延时函数指针
 * @param   led_index_t *const index           LED实例索引
 *
 * @return  led_handler_status_t 函数运行状态
 *
 * @retval  HANDLER_OK                操作成功
 * @retval  HANDLER_ERROR_RESOURCES   led实例挂载容量已满
 * @retval  HANDLER_ERROR_PARAMETER   传入参数错误
 */
led_handler_status_t led_register( bsp_led_handler_t *const self,
                                   bsp_led_driver_t *const  led_driver,
                                   led_index_t *const       index )
{
    if ( NULL == self ||
         NULL == led_driver ||
         NULL == index )
    {
#ifdef DEBUG
        DEBUG_OUT( "led_register input parameter is error \r\n" );
#endif  // DEBUG
        return HANDLER_ERROR_PARAMETER;
    }

    if ( HANDLER_NOT_INITED == self->init_status )
    {
#ifdef DEBUG
        DEBUG_OUT( "led_register bsp_led_handler_t is not inited \r\n" );
#endif  // DEBUG
        return HANDLER_ERROR_PARAMETER;
    }

    if ( NOT_INITED == led_driver->init_status )
    {
#ifdef DEBUG
        DEBUG_OUT( "led_register bsp_led_driver_t is not inited \r\n" );
#endif  // DEBUG
        return HANDLER_ERROR_PARAMETER;
    }

    if ( ( MAX_INSTANCE_NUMBER - self->instances.led_instance_num ) == 0 )
    {
#ifdef DEBUG
        DEBUG_OUT( "led_register led_instance_num is full \r\n" );
#endif  // DEBUG
        return HANDLER_ERROR_RESOURCES;
    }

#ifdef OS_SUPPORTING
    self->p_os_critical->pf_os_critical_enter();
#endif  // OS_SUPPORTING

    if ( ( MAX_INSTANCE_NUMBER - self->instances.led_instance_num ) > 0 )
    {
        self->instances.led_instance_group
            [self->instances.led_instance_num] = led_driver;

        *index = (led_index_t)self->instances.led_instance_num;

        self->instances.led_instance_num++;
    }

#ifdef OS_SUPPORTING
    self->p_os_critical->pf_os_critical_exit();
#endif  // OS_SUPPORTING

    return HANDLER_OK;
}

/**
 * @brief   LED句柄控制led函数
 *
 * @param   bsp_led_handler_t *const self led句柄结构体指针
 * @param   uint32_t cycle                OS延时函数指针
 * @param   uint32_t blink_times          OS队列操作函数结构体指针
 * @param   led_duty_cycle_t duty_cycle   OS临界区操作函数结构体指针
 * @param   led_index_t const index       OS线程操作函数结构体指针
 *
 * @return  led_handler_status_t 函数运行状态
 *
 * @retval  HANDLER_OK                操作成功
 * @retval  HANDLER_ERROR             队列发送函数错误
 * @retval  HANDLER_ERROR_PARAMETER   传入参数错误
 */
led_handler_status_t handler_led_control( bsp_led_handler_t *const self,
                                          uint32_t                 cycle,
                                          uint32_t                 blink_times,
                                          led_duty_cycle_t         duty_cycle,
                                          led_index_t const        index )
{
    if ( NULL == self )
    {
#ifdef DEBUG
        DEBUG_OUT( "handler_led_control input parameter is error \r\n" );
#endif  // DEBUG
        return HANDLER_ERROR_PARAMETER;
    }
    if ( HANDLER_NOT_INITED == self->init_status )
    {
#ifdef DEBUG
        DEBUG_OUT( "handler_led_control  is not inited \r\n" );
#endif  // DEBUG
        return HANDLER_ERROR_PARAMETER;
    }

    // 判断数据合法性
    if ( !( ( cycle < 10000 ) &&
            ( blink_times < 1000 ) &&
            ( ( DUTY_CYCLE_1_1 <= duty_cycle ) && ( DUTY_CYCLE_1_3 >= duty_cycle ) ) ) )
    {
#ifdef DEBUG
        DEBUG_OUT( "handler_led_control input parameters are illegal data\r\n" );
#endif  // DEBUG
        return HANDLER_ERROR_PARAMETER;
    }

    led_handler_event_t led_handler_event = {
        .cycle       = cycle,
        .blink_times = blink_times,
        .duty_cycle  = duty_cycle,
        .index       = index };

    led_handler_status_t ret = HANDLER_OK;

    ret = self->p_os_queue->pf_os_queue_put(
        self->queue_handler,
        &led_handler_event,
        0 );

    if ( HANDLER_OK != ret )
    {
#ifdef DEBUG
        DEBUG_OUT( "handler_led_control pf_os_queue_put error\r\n" );
#endif  // DEBUG
        return HANDLER_ERROR;
    }

    return HANDLER_OK;
}

/**
 * @brief   LED句柄挂载函数
 *
 * @param   bsp_led_handler_t *const self            led句柄结构体指针
 * @param   handler_os_delay_t *const os_delay               OS延时函数指针
 * @param   handler_os_queue_t *const os_queue       OS队列操作函数结构体指针
 * @param   handler_os_critical_t *const os_critical OS临界区操作函数结构体指针
 * @param   handler_os_thread_t *const os_thread     OS线程操作函数结构体指针
 * @param   handler_time_base_ms_t *const time_base  时基函数指针
 *
 * @return  led_handler_status_t 函数运行状态
 *
 * @retval  HANDLER_OK                操作成功
 * @retval  HANDLER_ERROR_PARAMETER   传入参数错误
 */
led_handler_status_t
led_handler_inst( bsp_led_handler_t *const self,
#ifdef OS_SUPPORTING
                  handler_os_delay_t *const    os_delay,
                  handler_os_queue_t *const    os_queue,
                  handler_os_critical_t *const os_critical,
                  handler_os_thread_t *const   os_thread,
#endif  // OS_SUPPORTING
                  handler_time_base_t *const time_base )
{
    if ( NULL == self ||
#ifdef OS_SUPPORTING
         NULL == os_delay ||
         NULL == os_queue ||
         NULL == os_critical ||
         NULL == os_thread ||
#endif  // OS_SUPPORTING
         NULL == time_base )
    {
#ifdef DEBUG
        DEBUG_OUT( "led_handler_inst input parameter is error \r\n" );
#endif  // DEBUG
        return HANDLER_ERROR_PARAMETER;
    }

    if ( HANDLER_INITED == self->init_status )
    {
#ifdef DEBUG
        DEBUG_OUT( "led_handler_inst was inited \r\n" );
#endif  // DEBUG
        return HANDLER_ERROR_PARAMETER;
    }

#ifdef DEBUG
    DEBUG_OUT( "led_handler_inst start\r\n" );
#endif  // DEBUG

    self->p_time_base = time_base;
#ifdef OS_SUPPORTING
    self->p_os_time_delay = os_delay;
    self->p_os_queue      = os_queue;
    self->p_os_critical   = os_critical;
    self->p_os_thread     = os_thread;
#endif  // OS_SUPPORTING

    self->pf_led_countroler = handler_led_control;
    self->pf_led_register   = led_register;

    led_handler_status_t ret = HANDLER_OK;
    ret                      = self->p_os_thread->pf_os_thread_create(
        handler_thread,
        "handler_thread",
        256,
        self,
        0,
        &self->thread_handler );

    self->p_os_queue->pf_os_queue_create( 10,
                                          sizeof( led_handler_event_t ),
                                          &( self->queue_handler ) );

    if ( HANDLER_OK != ret )
    {
#ifdef DEBUG
        DEBUG_OUT( "HANDLER_ERRORNOMEMORY at pf_os_thread_create\r\n" );
#endif  // DEBUG
        self->p_os_thread->pf_os_thread_delete( self->thread_handler );
        return ret;
    }

    self->instances.led_instance_num = 0;

    ret = __array_init( self->instances.led_instance_group,
                        MAX_INSTANCE_NUMBER );
    if ( HANDLER_OK != ret )
    {
#ifdef DEBUG
        DEBUG_OUT( "HANDLER_ERRORNOMEMORY at __array_init\r\n" );
#endif  // DEBUG

        self->p_os_thread->pf_os_thread_delete( self->thread_handler );
        self->p_os_queue->pf_os_queue_delete( self->queue_handler );
        return ret;
    }

    self->init_status = HANDLER_INITED;

#ifdef DEBUG
    DEBUG_OUT( "LED handler init finished\r\n" );
#endif  // DEBUG

    return ret;
}

//******************************** Declaring ********************************//
